{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "provenance": [],
      "gpuType": "T4"
    },
    "kernelspec": {
      "name": "python3",
      "display_name": "Python 3"
    },
    "language_info": {
      "name": "python"
    },
    "accelerator": "GPU"
  },
  "cells": [
    {
      "cell_type": "markdown",
      "source": [
        "# Create meeting minutes from an Audio file\n",
        "For this project, the UI allows you to either upload meeting minutes, or record something of your own!"
      ],
      "metadata": {
        "id": "MYOLn_FzYAF4"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "# --- Install deps ---\n",
        "!pip install -q gradio torch==2.5.1+cu124 torchvision==0.20.1+cu124 torchaudio==2.5.1+cu124 --index-url https://download.pytorch.org/whl/cu124\n",
        "!pip install -q requests bitsandbytes==0.46.0 transformers==4.48.3 accelerate==1.3.0 openai"
      ],
      "metadata": {
        "id": "M01YO75ITfXF"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "# --- Imports ---\n",
        "import gradio as gr\n",
        "import torch\n",
        "from transformers import AutoTokenizer, AutoModelForCausalLM, TextStreamer, BitsAndBytesConfig\n",
        "from openai import OpenAI\n",
        "from huggingface_hub import login\n",
        "from google.colab import userdata\n",
        "from google.colab import drive\n",
        "import os"
      ],
      "metadata": {
        "id": "DGE8_oAwZJBo"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "# --- Constants ---\n",
        "AUDIO_MODEL = \"whisper-1\"\n",
        "LLAMA = \"meta-llama/Meta-Llama-3.1-8B-Instruct\""
      ],
      "metadata": {
        "id": "JPu-aNxDTmDi"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "# --- Auth ---\n",
        "# assumes Colab userdata or your own env vars\n",
        "hf_token = userdata.get('HF_TOKEN')\n",
        "login(hf_token, add_to_git_credential=True)"
      ],
      "metadata": {
        "id": "JfWUrEVJTmET"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "openai_api_key = userdata.get('OPENAI_API_KEY')\n",
        "openai = OpenAI(api_key=openai_api_key)"
      ],
      "metadata": {
        "id": "AiUtJ0mjTpVE"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "# --- Model setup ---\n",
        "quant_config = BitsAndBytesConfig(\n",
        "    load_in_4bit=True,\n",
        "    bnb_4bit_use_double_quant=True,\n",
        "    bnb_4bit_compute_dtype=torch.bfloat16,\n",
        "    bnb_4bit_quant_type=\"nf4\"\n",
        ")\n",
        "\n",
        "tokenizer = AutoTokenizer.from_pretrained(LLAMA)\n",
        "tokenizer.pad_token = tokenizer.eos_token\n",
        "model = AutoModelForCausalLM.from_pretrained(\n",
        "    LLAMA, device_map=\"auto\", quantization_config=quant_config\n",
        ")"
      ],
      "metadata": {
        "id": "hMb4dggMW2s5"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "XTEW5qAwRN4Y"
      },
      "outputs": [],
      "source": [
        "# --- Processing function ---\n",
        "def process_meeting(audio_file):\n",
        "    # Step 1: Transcribe\n",
        "    with open(audio_file, \"rb\") as f:\n",
        "        transcription = openai.audio.transcriptions.create(\n",
        "            model=AUDIO_MODEL, file=f, response_format=\"text\"\n",
        "        )\n",
        "\n",
        "    # Step 2: Prepare prompt\n",
        "    system_message = (\n",
        "        \"You are an assistant that produces minutes of meetings from transcripts, \"\n",
        "        \"with summary, key discussion points, takeaways and action items with owners, \"\n",
        "        \"in markdown.\"\n",
        "    )\n",
        "    user_prompt = (\n",
        "        f\"Below is an extract transcript of a meeting. Please write minutes in markdown, \"\n",
        "        f\"including a summary with attendees, location and date; discussion points; \"\n",
        "        f\"takeaways; and action items with owners.\\n{transcription}\"\n",
        "    )\n",
        "    messages = [\n",
        "        {\"role\": \"system\", \"content\": system_message},\n",
        "        {\"role\": \"user\", \"content\": user_prompt}\n",
        "    ]\n",
        "\n",
        "    # Step 3: Run through LLaMA\n",
        "    inputs = tokenizer.apply_chat_template(messages, return_tensors=\"pt\").to(\"cuda\")\n",
        "    streamer = TextStreamer(tokenizer, skip_prompt=True, skip_special_tokens=True)\n",
        "    outputs = model.generate(inputs, max_new_tokens=2000)\n",
        "\n",
        "    response = tokenizer.decode(outputs[0], skip_special_tokens=True)\n",
        "    return response\n",
        "\n",
        "# --- Gradio UI ---\n",
        "with gr.Blocks() as demo:\n",
        "    gr.Markdown(\"## 📝 Meeting Minutes Generator\\nUpload an audio file and get structured meeting minutes.\")\n",
        "    with gr.Row():\n",
        "        audio_in = gr.Audio(type=\"filepath\", label=\"Upload Meeting Audio\")\n",
        "    btn = gr.Button(\"Generate Minutes\")\n",
        "    md_out = gr.Markdown()\n",
        "\n",
        "    btn.click(fn=process_meeting, inputs=audio_in, outputs=md_out)"
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "demo.launch()"
      ],
      "metadata": {
        "id": "Yh4-imrmY8MH"
      },
      "execution_count": null,
      "outputs": []
    }
  ]
}